package com.monkey.service;

import com.monkey.core.ErrorCode;
import com.monkey.core.WebRet;
import com.monkey.generator.dao.TMonkeyFeedMapper;
import com.monkey.generator.dao.TUserFeedMapper;
import com.monkey.generator.model.TMonkey;
import com.monkey.generator.model.TMonkeyFeed;
import com.monkey.generator.model.TMonkeyFeedExample;
import com.monkey.generator.model.TUserFeed;
import com.monkey.model.monkey.Monkey;
import com.monkey.model.monkey.MonkeyFeed;
import com.monkey.model.user.User;
import com.monkey.util.DateUtil;
import com.monkey.util.IDGenerator;
import com.monkey.util.WebConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

import static com.monkey.service.MonkeyService.MONKEY_STATUS_FEED;
import static com.monkey.service.UserService.ACTION_FEED;

/**
 * desc:
 * auth: chenxiaobin
 * data: 2018/1/12.
 */
@Service
@Transactional
public class FeedService {
    private static Logger logger = LoggerFactory.getLogger(FeedService.class);
    public static final int FEED_STATUS1 = 1; // 普通
    public static final int FEED_STATUS2 = 2; // 完美
    public static final int FEED_STATUS3 = 3; // 大完美

    @Resource
    private UserService userService = null;

    @Resource
    private MonkeyService monkeyService = null;

    @Resource
    private TMonkeyFeedMapper monkeyFeedMapper = null;

    @Resource
    private TUserFeedMapper userFeedMapper = null;

    @Resource
    private DateUtil dateUtil = null;

    @Resource
    private IDGenerator idGenerator = null;

    @Resource
    private WebConfig webConfig = null;

    public WebRet feed(User user, int monkeyId, int price) {
        int userId = user.getId();

        // 是否绑定钱包
        if (user.getWallet().isEmpty()) {
            return new WebRet(ErrorCode.WALLET_NO_BIND);
        }

        // 是否激活账号
        if (!user.getEnable()) {
            return new WebRet(ErrorCode.ACCOUNT_DISABLE);
        }

        if (price <= 0) {
            return new WebRet(ErrorCode.ORDER_LESS_ZERO);
        }

        Monkey monkey = monkeyService.getMonkey(monkeyId);
        if (null == monkey) {
            return new WebRet(ErrorCode.GET_DATA_ERROR);
        }
        int count = webConfig.getInt("feed.count.max");

        // 余额不足
        int min = webConfig.getInt("feed.pay.min");
        int max = webConfig.getInt("feed.pay.max");
        if (price < min && price > max) {
            return new WebRet(ErrorCode.FEED_PRICE_ERROR);
        }
        if (user.getMoney().floatValue() < price) {
            return new WebRet(ErrorCode.WALLET_LESS_ERROR);
        }

        // 增加次数
        Date now = new Date();
        SimpleDateFormat sdf1 = dateUtil.getSimpleDateFormat();
        String feedTime = sdf1.format(now);

        synchronized (this) {
            // 总金额判断
            if (monkey.getFeedMoney() >= count) {
                return new WebRet(ErrorCode.FEED_COUNT_ERROR);
            }
            if (monkey.getFeedMoney() + price > count) {
                return new WebRet(ErrorCode.FEED_COUNT_ERROR);
            }

            monkey.setFeedCount(monkey.getFeedCount() + 1);
            monkey.setFeedMoney(monkey.getFeedMoney() + price);
            monkey.setFeedTime(feedTime);
        }

        // 记录次数
        TMonkeyFeed feed1 = new TMonkeyFeed();
        feed1.setCount(monkey.getFeedCount());
        feed1.setMoney(monkey.getFeedMoney());
        feed1.setFeedtime(monkey.getFeedTime());
        TMonkeyFeedExample example = new TMonkeyFeedExample();
        example.or().andMonkeyidEqualTo(monkeyId);
        example.setLimit(1);
        if (0 == monkeyFeedMapper.updateByExampleSelective(feed1, example)) {
            logger.info("feed update monkey feed error:{}, {}", userId, monkeyId);
        }

        // 扣钱
        if (ErrorCode.SUCCESS != userService.updateUserMoney(user, monkeyId, -price, price, MONKEY_STATUS_FEED, ACTION_FEED)) {
            return new WebRet(ErrorCode.WRITE_DB_ERROR);
        }

        // 喂食，生成hash
        String uuid = idGenerator.randomUUID();
        String end = uuid.substring(uuid.length() - 1);
        int status = FEED_STATUS1;
        int weightUp = 0;
        int growUp = 0;
        int reproductUp = 0;
        int bonusUp = 0;
        if (end.equals("8")) {
            status = FEED_STATUS3;
            weightUp = monkey.getGrow() * price * 2;
        } else if (end.equals("6") || end.equals("9")) {
            status = FEED_STATUS2;
            weightUp = (int) (monkey.getGrow() * price * 1.5);
        } else {
            weightUp = monkey.getGrow() * price;
        }

        // 计算衰减
        int base = webConfig.getInt("feed.decay.base") * 100;
        float percent = webConfig.getFloat("feed.decay.percent");
        base = monkey.getWeight() / base;
        if (0 != base) {
            logger.info("feed decay:{}, {}, {}, {}, {}", monkeyId, monkey.getWeight(), weightUp, base, percent);
            weightUp = (int) (weightUp * Math.pow(percent, base));
        }

        // 体重
        TMonkey monkey1 = new TMonkey();
        monkey.setWeight(monkey.getWeight() + weightUp);
        monkey1.setWeight(monkey.getWeight());
        if (0 == monkeyService.updateMonkey(monkeyId, monkey1)) {
            logger.info("feed update monkey error:{}, {}", userId, monkeyId);
        }

        // 记录喂食
        SimpleDateFormat sdf = dateUtil.getDateFormat();
        TUserFeed feed = new TUserFeed();
        feed.setUserid(userId);
        feed.setMonkeyid(monkeyId);
        feed.setWeight(weightUp);
        feed.setGrow(growUp);
        feed.setReproduct(reproductUp);
        feed.setBonus(bonusUp);
        feed.setMoney(price);
        feed.setStatus(status);
        feed.setUuid(uuid);
        feed.setCreatetime(now);
        if (0 == userFeedMapper.insert(feed)) {
            logger.info("feed insert user feed error:{}, {}", userId, monkeyId);
        }

        // 插入记录
        max = webConfig.getInt("feed.view.max");
        List<MonkeyFeed> feeds = monkey.getFeeds();
        int size = feeds.size();
        if (size >= max) {
            feeds.remove(size - 1);
        }
        feeds.add(0, new MonkeyFeed(feed, sdf));

        logger.info("feed:{}, {}, w:{}, g:{}, r:{}, b:{}, p:{}", userId, monkeyId, weightUp, growUp, reproductUp, bonusUp, price);
        return new WebRet(ErrorCode.SUCCESS);
    }
}
